#define _USE_MATH_DEFINES
#include "Echo.h"
#include <iostream>
#include <stdlib.h>
#include <math.h>

using namespace std;

Echo::~Echo() { }

Echo::Echo(int rowsCount, int samplesCount) {
    this->rowsCount = rowsCount;        // wiersz antenowy 
    this->samplesCount = samplesCount;    // próbkowanie
    for(int rowNumber = 0; rowNumber < rowsCount; rowNumber++) {
        vector<complex<double> > rowVector;
        for(int probeNumber = 0; probeNumber < samplesCount; probeNumber++) {
            rowVector.push_back(generateWhiteGaussianNoise());
        }
        echo.push_back(rowVector);
    }
}

unsigned long Echo::rdtsc() {
    unsigned int lo, hi;
    __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi));
    return ((unsigned long long)hi << 32) | lo;
}

vector<complex<double> > Echo::getRowVector(int rowNumber) {
    vector<complex<double> > rowVector = echo.at(rowNumber);
    return rowVector;
}

vector<complex<double> > Echo::getSampleVector(int sampleNumber) {      
    vector<complex<double> > sampleVector;
    for(int rowNumber=0; rowNumber<rowsCount; rowNumber++) {
        sampleVector.push_back(echo.at(rowNumber).at(sampleNumber));
    }
    return sampleVector;
}

complex<double> Echo::getSingleSample(int rowNumber, int sampleNumber) {
    return this->echo.at(rowNumber).at(sampleNumber);
}

int Echo::getSamplesCount() {
    return this->samplesCount;
}

int Echo::getRowsCount() {
    return this->rowsCount;
}

complex<double> Echo::generateWhiteGaussianNoise() {
    srand(rdtsc());
    double rnd1 = (double)rand()/RAND_MAX;
    srand(rdtsc());
    double rnd2 = (double)rand()/RAND_MAX;
//    Box-Muller
    double phi = 2*M_PI*rnd2;
    double real = sqrt(-2*log(rnd1))*cos(phi); 
    double imag = sqrt(-2*log(rnd1))*sin(phi);
    return complex<double>(real, imag);
}

vector<vector<complex<double> > > Echo::getEcho() {
    return this->echo;
}

